/*
 * MultiPhase.h
 *
 *  Created on: 21 Jul 2011
 *      Author: Allan
 */

#ifndef MULTIPHASE_H_
#define MULTIPHASE_H_

// C++ includes
#include <vector>
using namespace std;

// GeoReact includes
#include "Phase.h"

class MultiPhase
{
public:
	MultiPhase();
	
	MultiPhase(const vector<PhasePtr>& phases);
	
	virtual ~MultiPhase();
	
	/// --- Getter methods --- ///
	const vector<PhasePtr>&
	GetPhases() const;
	
	const StringVector&
	GetSpecies() const;
	
	const Index
	GetSpeciesIndex(const String& speciesName) const;
	
	const IndexVector
	GetSpeciesIndexes(const StringVector& speciesNames) const;
	
	const Index
	operator[](const String& speciesName) const;
	
	const IndexVector
	operator[](const StringVector& speciesNames) const;
	
	/// --- Computation methods --- ///
	const DoubleVector
	ActivityCoefficients(double T, double P, const DoubleVector& n) const;
	
	const DoubleVector
	Activities(double T, double P, const DoubleVector& n) const;
	
private:
	vector<PhasePtr> phases;
	
	StringVector species;
	
	bool isOpen;
	
private:
	template<class PhaseFunction> const DoubleVector
	GenericPhaseComputation(double T, double P, const DoubleVector& n, const PhaseFunction& phaseFunction) const;
};

template<class PhaseFunction> 
const DoubleVector MultiPhase::GenericPhaseComputation(double T, double P, const DoubleVector& n, const PhaseFunction& phaseFunction) const
{
	// The activity-like data of the species to be computed
	DoubleVector a(species.size());
	
	// The current number of processed species, to be update at the end of every loop (see below)
	Index nprocessed = 0;
	
	// Loop over all the phases
	BOOST_FOREACH(const PhasePtr& phase, phases)
	{
		// The number of species in the current phase
		const uint nspecies = phase->GetSpecies().size();
		
		// The vector of number of moles of the species of the current phase (note the interval: nprocessed to nprocessed + nspecies)
		const DoubleVector np(n.begin() + nprocessed, n.begin() + nprocessed + nspecies);
		
		// Compute the activity-like data of the species in the current phase using the template parameter phaseFunction
		DoubleVector ap = phaseFunction(phase, T, P, np);
		
		// Transfer the activity-like data of the current phase to the vector of activity-like data a (beginning at position given by nprocessed)
		std::transform(ap.begin(), ap.end(), a.begin() + nprocessed, [&](double val) { return val; });
		
		// Update the number of processed species
		nprocessed += nspecies;
	}

	return a;
}

#endif /* MULTIPHASE_H_ */
